#include <kuai/typedef.h>
#include <boost/utility.hpp>

#ifndef _KUAILIB_CT_H_
#define _KUAILIB_CT_H_

namespace kuai {

	/**
	* A Connect Table use a connected buffer to store the connection info of a moelcule.
	*/
	class ConnectTable 
		: public boost::noncopyable
	{
	public:
		explicit ConnectTable(const Index v[]) ;
		explicit ConnectTable(Index nAtoms, const Index atoms[], Index nBonds, const Index bonds[], Index buffer[]) ;

	public:
		static Index count_size(Index nAtoms, Index nBonds);

		Index count_atoms() const {
			return _nAtoms;
		}

		Index count_bonds() const {
			return _nBonds;
		}

		Index atom(Index i) const {
			return _atoms[i];
		}

		Index bond_atom_1(Index i) const {
			return _bonds[i*2];
		}
		Index bond_atom_2(Index i) const {
			return _bonds[i*2+1];
		}

		Index degree(Index i) const {
			return _degree[i];
		}
		Index neighbor_atom(Index iAtom, Index j) const {
			return _adjs[_offset[iAtom]+j*2];
		}
		Index neighbor_bond(Index iAtom, Index j) const {
			return _adjs[_offset[iAtom]+j*2+1];
		}

		Index bridge(Index iAtom1, Index iAtom2) const {
			Index d = degree(iAtom1);
			for (Index i = 0; i < d; ++i) {
				if (neighbor_atom(iAtom1, d) == iAtom2) {
					return neighbor_bond(iAtom1, d);
				}
			}
			return INVALID_INDEX;
		}

	private:
		Index _nAtoms, _nBonds;
		const Index* _atoms;
		const Index* _bonds;
		const Index* _degree;
		const Index* _offset;
		const Index* _adjs;

	private:
		void _setup(Index adjs[], Index atom1, Index atom2, Index bond);
	};

	BigIndex count_masks(Index nAtoms);
	void set_mask(const Index atoms[], BigIndex nList, Index gap, Byte masks[]);
	bool test_bit(const Byte masks[], Index i, Index j);

	BigIndex offset(Index i, Index j);

}

#endif
